function* generateSequence1() {
  yield 1;
  yield 2;
  return 3;
}

/**
 * 函数的基本使用
 */
let generator = generateSequence1();
console.info(generator); // [object Generator]
console.info(generator.next()); //=>{ value: 1, done: false }
console.info(generator.next()); //=>{ value: 2, done: false }
console.info(generator.next()); //=>{ value: 3, done: true }

/**
 * 函数迭代
 */
for (let value of generator) {
  console.info(value); // 1，然后是 2
}
function* generateSequence2() {
  yield 1;
  yield 2;
  yield 3;
}
for (let value of generateSequence2()) {
  console.info(value); // 1，然后是 2
}

/**
 * 使用 generator 进行迭代
 */
let range = {
  from: 1,
  to: 5,

  // for..of range 在一开始就调用一次这个方法
  [Symbol.iterator]() {
    // ...它返回 iterator object：
    // 后续的操作中，for..of 将只针对这个对象，并使用 next() 向它请求下一个值
    return {
      current: this.from,
      last: this.to,

      // for..of 循环在每次迭代时都会调用 next()
      next() {
        // 它应该以对象 {done:.., value :...} 的形式返回值
        if (this.current <= this.last) {
          return { done: false, value: this.current++ };
        } else {
          return { done: true };
        }
      },
    };
  },
};

// 迭代整个 range 对象，返回从 `range.from` 到 `range.to` 范围的所有数字
console.info([...range]); // 1,2,3,4,5

let range1 = {
  from: 1,
  to: 5,

  *[Symbol.iterator]() {
    // [Symbol.iterator]: function*() 的简写形式
    for (let value = this.from; value <= this.to; value++) {
      yield value;
    }
  },
};

console.info([...range1]); // 1,2,3,4,5

/**
 * generator 组合
 */
function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) yield i;
}

function* generatePasswordCodes() {
  // 0..9
  yield* generateSequence(48, 57);

  // A..Z
  yield* generateSequence(65, 90);

  // a..z
  yield* generateSequence(97, 122);
}

let str = "";

for (let code of generatePasswordCodes()) {
  str += String.fromCharCode(code);
}

console.info(str); // 0..9A..Za..z

/**
 * “yield” 是一条双向路
 */

function* gen() {
  // 向外部代码传递一个问题并等待答案
  let result = yield "2 + 2 = ?"; // (*)

  console.info(result);
}

let generator2 = gen();

let question = generator2.next().value; // <-- yield 返回的 value

generator2.next(4); // --> 将结果传递到 generator 中

/**
 * generator.throw
 */
// function* gen() {
//   try {
//     let result = yield "2 + 2 = ?"; // (1)

//     console.info(
//       "The execution does not reach here, because the exception is thrown above"
//     );
//   } catch (e) {
//     console.info(e); // 显示这个 error
//   }
// }

// let generator3 = gen();

// let question3 = generator3.next().value;

// generator3.throw(new Error("The answer is not found in my database")); // (2)

/**
 * generator.return
 */

function* gen4() {
  yield 1;
  yield 2;
  yield 3;
}

const g = gen4();

console.info(g.next()); // { value: 1, done: false }
console.info(g.return("foo")); // { value: "foo", done: true }
console.info(g.next()); // { value: undefined, done: true }
